<!doctype html>
<html lang="zh-cn">
  <head>
    <title>多任务编程(2) // JW Blog</title>
    <meta charset="utf-8" />
    <meta name="generator" content="Hugo 0.60.1" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="author" content="John Doe" />
    <meta name="description" content="" />
    <link rel="stylesheet" href="https://duyi111.gitee.io/css/main.min.f90f5edd436ec7b74ad05479a05705770306911f721193e7845948fb07fe1335.css" />

    
    <meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="多任务编程(2)"/>
<meta name="twitter:description" content="1.线程 1.1 线程的概念  线程是实现多任务的另外一种方式 线程是进程中执行代码的一个分支，每个执行分支（线程）要想工作执行代码需要CPU调度，也就是说线程是CPU调度的基本单位，每个进程至少都有一个线程，而这个线程就是常说的主线程。  1.2 多线程的使用  导入线程模块 import threading  创建子线程并指定执行的任务 sub_thread = threading.Thread(target = 任务名)  启动线程执行任务 sub_thread.start()   1.3 线程类Thread参数说明  Thread([group [, target [, name [, args [, kwargs]]]]])  group：线程组 target：执行的目标任务名 args：以元组的方式给执行任务传参 kwargs：以字典的方式给执行任务传参 name：线程名，一般不用设置    1.4 线程执行带有参数的任务  Thread类执行任务并给任务传参数的方式：  args：表示以元组的方式给执行任务传参  元组方式传参一定要和参数的顺序保持一致   kwargs：表示以字典的方式给执行任务传参  字典方式传参字典中的key一定要和参数名保持一致      2.线程的注意点 2.1 线程之间执行时无序的  线程之间执行是无序的，它是由CPU调度决定的，CPU调度哪个线程，哪个线程就先执行，没有调度的线程不能执行。 进程之间执行也是无序的，它是由操作系统调度决定的，操作系统调度哪个进程，哪个进程就先执行，没有调度的进程不能执行。  2."/>

    <meta property="og:title" content="多任务编程(2)" />
<meta property="og:description" content="1.线程 1.1 线程的概念  线程是实现多任务的另外一种方式 线程是进程中执行代码的一个分支，每个执行分支（线程）要想工作执行代码需要CPU调度，也就是说线程是CPU调度的基本单位，每个进程至少都有一个线程，而这个线程就是常说的主线程。  1.2 多线程的使用  导入线程模块 import threading  创建子线程并指定执行的任务 sub_thread = threading.Thread(target = 任务名)  启动线程执行任务 sub_thread.start()   1.3 线程类Thread参数说明  Thread([group [, target [, name [, args [, kwargs]]]]])  group：线程组 target：执行的目标任务名 args：以元组的方式给执行任务传参 kwargs：以字典的方式给执行任务传参 name：线程名，一般不用设置    1.4 线程执行带有参数的任务  Thread类执行任务并给任务传参数的方式：  args：表示以元组的方式给执行任务传参  元组方式传参一定要和参数的顺序保持一致   kwargs：表示以字典的方式给执行任务传参  字典方式传参字典中的key一定要和参数名保持一致      2.线程的注意点 2.1 线程之间执行时无序的  线程之间执行是无序的，它是由CPU调度决定的，CPU调度哪个线程，哪个线程就先执行，没有调度的线程不能执行。 进程之间执行也是无序的，它是由操作系统调度决定的，操作系统调度哪个进程，哪个进程就先执行，没有调度的进程不能执行。  2." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://duyi111.gitee.io/post/%E5%A4%9A%E4%BB%BB%E5%8A%A1%E7%BC%96%E7%A8%8B2/" />
<meta property="article:published_time" content="2020-01-28T21:09:33+08:00" />
<meta property="article:modified_time" content="2020-01-28T21:09:33+08:00" />


  </head>
  <body>
    <header class="app-header">
      <a href="https://duyi111.gitee.io/"><img class="app-header-avatar" src="/avatar.jpg" alt="John Doe" /></a>
      <h1>JW Blog</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vehicula turpis sit amet elit pretium.</p>
      <div class="app-header-social">
        
      </div>
    </header>
    <main class="app-container">
      
  <article class="post">
    <header class="post-header">
      <h1 class ="post-title">多任务编程(2)</h1>
      <div class="post-meta">
        <div>
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-calendar">
  <title>calendar</title>
  <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
          Jan 28, 2020
        </div>
        <div>
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-clock">
  <title>clock</title>
  <circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>
</svg>
          1 min read
        </div></div>
    </header>
    <div class="post-content">
      <h2 id="1">1.线程</h2>
<h4 id="11-">1.1 线程的概念</h4>
<ul>
<li>线程是实现多任务的另外一种方式</li>
<li>线程是进程中执行代码的一个分支，每个执行分支（线程）要想工作执行代码需要CPU调度，也就是说线程是CPU调度的基本单位，每个进程至少都有一个线程，而这个线程就是常说的主线程。</li>
</ul>
<h4 id="12-">1.2 多线程的使用</h4>
<ul>
<li>导入线程模块
<pre><code>import threading
</code></pre></li>
<li>创建子线程并指定执行的任务
<pre><code>sub_thread = threading.Thread(target = 任务名)
</code></pre></li>
<li>启动线程执行任务
<pre><code>sub_thread.start()
</code></pre></li>
</ul>
<h4 id="13-thread">1.3 线程类Thread参数说明</h4>
<ul>
<li>Thread([group [, target [, name [, args [, kwargs]]]]])
<ul>
<li>group：线程组</li>
<li>target：执行的目标任务名</li>
<li>args：以元组的方式给执行任务传参</li>
<li>kwargs：以字典的方式给执行任务传参</li>
<li>name：线程名，一般不用设置</li>
</ul>
</li>
</ul>
<h4 id="14-">1.4 线程执行带有参数的任务</h4>
<ul>
<li>Thread类执行任务并给任务传参数的方式：
<ul>
<li>args：表示以元组的方式给执行任务传参
<ul>
<li>元组方式传参一定要和参数的顺序保持一致</li>
</ul>
</li>
<li>kwargs：表示以字典的方式给执行任务传参
<ul>
<li>字典方式传参字典中的key一定要和参数名保持一致</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="2">2.线程的注意点</h2>
<h4 id="21-">2.1 线程之间执行时无序的</h4>
<ul>
<li>线程之间执行是无序的，它是由CPU调度决定的，CPU调度哪个线程，哪个线程就先执行，没有调度的线程不能执行。</li>
<li>进程之间执行也是无序的，它是由操作系统调度决定的，操作系统调度哪个进程，哪个进程就先执行，没有调度的进程不能执行。</li>
</ul>
<h4 id="22-">2.2 主线程默认会等待所有的子线程执行结束再结束</h4>
<ul>
<li>如何保证主线程正常退出
<ul>
<li>设置守护主线程
<ul>
<li><code>threading.Thread(target = 任务名, daemon = True)</code></li>
<li><code>线程对象.setDaemon(True)</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="23-">2.3 线程之间共享全局变量</h4>
<h4 id="24-">2.4 线程之间共享全局变量数据出现错误问题</h4>
<ul>
<li>全局变量数据错误的解决方法：
<ul>
<li>线程同步：保证同一时刻只能有一个线程去操作全局变量；同步：就是协同步调，按预定的先后次序进行运行</li>
</ul>
</li>
<li>线程同步的方式：
<ul>
<li>线程等待（<code>join</code>）</li>
<li>互斥锁</li>
</ul>
</li>
</ul>
<h2 id="3">3.互斥锁</h2>
<h4 id="31-">3.1 概念</h4>
<ul>
<li>互斥锁：对数据进行锁定，保证同一时刻只能有一个线程去操作</li>
<li>互斥锁是多个线程一起抢，抢到锁的线程先执行，没有抢到锁的线程需要等待，等互斥锁使用完释放后，其他等待的线程再去抢这个锁</li>
</ul>
<h4 id="32-">3.2 互斥锁的使用</h4>
<ul>
<li>创建锁
<pre><code>锁名（变量名） = threading.Lock()
</code></pre></li>
<li>上锁
<pre><code>锁名.acquire()
</code></pre></li>
<li>释放锁
<pre><code>锁名.release()
</code></pre></li>
<li>注意点
<ul>
<li>acquire和release方法之间的代码同一时刻只能有一个线程去操作。</li>
<li>如果在调用acquire方法的时候，其他线程已经使用了这个互斥锁，那么此时acquire方法会堵塞，直到这个互斥锁释放后才能再次上锁。</li>
</ul>
</li>
</ul>
<h4 id="33-">3.3 小结</h4>
<ul>
<li>互斥锁的作用就是保证同一时刻只能有一个线程去操作共享数据，保证共享数据不会出现错误问题。</li>
<li>使用互斥锁的好处是确保某段关键代码只能由一个线程从头到尾完整地去执行。</li>
<li>使用互斥锁会影响代码的执行效率，多任务改成了单任务执行。</li>
<li>互斥锁如果没有使用好容易出现死锁的情况。</li>
</ul>
<h2 id="4">4.死锁</h2>
<h4 id="41-">4.1 概念</h4>
<ul>
<li>死锁：一直等待对方释放锁的情景就是死锁</li>
<li>死锁的结果
<ul>
<li>会造成应用程序的停止响应，不能再处理其它任务了。</li>
</ul>
</li>
</ul>
<h4 id="42-">4.2 小结</h4>
<ul>
<li>使用互斥锁的时候需要注意死锁的问题，要在合适的地方注意释放锁。</li>
<li>死锁一旦产生就会造成应用程序的停止响应，应用程序无法再继续往下执行了</li>
</ul>
<h2 id="5">5.进程与线程的对比</h2>
<h4 id="51-">5.1 关系对比</h4>
<ul>
<li>线程是依附在进程里面的，没有进程就没有线程。</li>
<li>一个进程默认提供一条线程，进程可以创建多个线程。</li>
</ul>
<h4 id="52-">5.2 区别对比</h4>
<ul>
<li>1.进程之间不共享全局变量</li>
<li>2.线程之间共享全局变量，但是要注意资源竞争的问题，解决方法：互斥锁或者线程同步。</li>
<li>3.创建进程的资源开销要比创建线程的资源开销要大。</li>
<li>4.进程是操作系统资源分配的基本单位，线程是CPU调度的基本单位。</li>
<li>5.线程不能够独立执行，必须依存在进程中。</li>
<li>6.多进程开发比单进程多线程开发稳定性要强。</li>
</ul>
<h4 id="53-">5.3 优缺点对比</h4>
<ul>
<li>进程优缺点：
<ul>
<li>优点：可以用多核</li>
<li>缺点：资源开销大</li>
</ul>
</li>
<li>线程优缺点：
<ul>
<li>优点：资源开销小</li>
<li>缺点：不能使用多核</li>
</ul>
</li>
</ul>
<h4 id="54-">5.4 小结</h4>
<ul>
<li>进程和线程都是完成多任务的一种方式。</li>
<li>多进程要比多线程消耗的资源多，但是多进程开发要比单进程多线程开发稳定性要强，某个进程挂掉不会影响其他进程。</li>
<li>多进程可以使用CPU的多核运行，多线程可以共享全局变量。</li>
<li>线程不能单独执行必须依附在进程里面。</li>
</ul>

    </div>
    <div class="post-footer">
      
    </div>
  </article>

    </main>
  </body>
</html>
